/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: Dec 31, 2009
 * Time: 11:18:23 AM
 * To change this template use File | Settings | File Templates.
 */

import dk.brics.automaton.Automaton;
import java.util.*;
import org.jdom.*;

// Referenced classes of package dk.brics.dsd:
//            Declaration, Schema, Regexp, AttributeBoolexp,
//            Context, Validator

class AttributeDeclaration extends Declaration
{

    AttributeDeclaration(Element element, Schema schema)
    {
        name = element.getAttributeValue("name");
        if(name != null)
        {
            name_local = Schema.pnameLocal(name);
            name_uri = Schema.panameURI(name, element);
            name_prefix = Schema.pnamePrefix(name);
        }
        Iterator iterator = element.getChildren().iterator();
        do
        {
            if(!iterator.hasNext())
                break;
            Element element1 = (Element)iterator.next();
            if(Schema.isDSDElement(element1))
            {
                String s1 = element1.getName();
                if(s1.equals("normalize"))
                {
                    whitespace = element1.getAttributeValue("whitespace");
                    ccase = element1.getAttributeValue("case");
                } else
                if(s1.equals("default"))
                    ddefault = element1.getAttributeValue("value");
                else
                    regexp = Regexp.parse(element1, schema);
            }
        } while(true);
        String s = element.getAttributeValue("type");
        qname = s != null && s.equals("qname");
        qaname = s != null && s.equals("qaname");
    }

    public Element toXML(Context context)
    {
        Element element = new Element("attribute", "http://www.brics.dk/DSD/2.0");
        if(name != null)
            Schema.addPname(element, name, name_uri);
        if(regexp != null)
            element.addContent(regexp.toXML(context));
        return element;
    }

    static boolean checkQname(String s, Element element)
    {
        return Regexp.isPname(s) && Schema.prefixDeclared(s, element);
    }

    byte evaluate(Context context)
    {
        return AttributeBoolexp.evaluate(context, name, name_local, name_uri, regexp, qname, qaname);
    }

    boolean attributeNameMatch(Attribute attribute, Context context)
    {
        if(name == null)
            return true;
        String s = null;
        if((!Template.isGap(attribute) || context.sg == null) && !attribute.getNamespacePrefix().equals(""))
            s = attribute.getNamespaceURI();
        return Schema.matchPAname(name_local, name_uri, attribute.getName(), s);
    }

    boolean attributeMatch(Attribute attribute, Context context)
    {
        if(regexp == null && (whitespace != null || ccase != null || ddefault != null) || !attributeNameMatch(attribute, context))
            return false;
        if(regexp == null)
            return true;
        String s = attribute.getValue();
        if(context.sg != null)
        {
            String s1 = (String)context.v.attribute_whitespace.get(attribute);
            String s2 = (String)context.v.attribute_case.get(attribute);
            if(s1 != null)
                if(s1.equals("compress"))
                    s = Validator.whitespaceString(false, s);
                else
                if(s1.equals("trim"))
                    s = Validator.whitespaceString(true, s);
            if(s2 != null)
                if(s2.equals("upper"))
                    s = s.toUpperCase();
                else
                if(s2.equals("lower"))
                    s = s.toLowerCase();
        }
        if((qname || qaname) && !checkQname(s, attribute.getParent()))
            return false;
        else
            return regexp.match(s, context);
    }

    boolean attributeMatchName(Attribute attribute, Context context)
    {
        if(regexp == null && (whitespace != null || ccase != null || ddefault != null) || !attributeNameMatch(attribute, context))
            return false;
        if(regexp == null)
            return true;
        String s = attribute.getValue();
        if(context.sg != null)
        {
            String s1 = (String)context.v.attribute_whitespace.get(attribute);
            String s2 = (String)context.v.attribute_case.get(attribute);
            if(s1 != null)
                if(s1.equals("compress"))
                    s = Validator.whitespaceString(false, s);
                else
                if(s1.equals("trim"))
                    s = Validator.whitespaceString(true, s);
            if(s2 != null)
                if(s2.equals("upper"))
                    s = s.toUpperCase();
                else
                if(s2.equals("lower"))
                    s = s.toLowerCase();
        }
        return regexp.match(s, context);
    }

    Automaton addAttributeLabels(String s, Context context, Automaton automaton)
    {
        if((name == null || name_local.equals(s)) && (regexp != null || whitespace == null && ccase == null && ddefault == null))
            if(regexp != null)
            {
                Automaton automaton1 = regexp.getAutomaton(context);
                if(automaton.isEmpty())
                {
                    automaton = automaton1;
                } else
                {
                    automaton = automaton.union(automaton1);
                    automaton.minimize();
                }
            } else
            {
                automaton = Automaton.makeAnyString();
            }
        return automaton;
    }

    void findDeclarations(List list)
    {
        list.add(this);
    }

    void collectAttributeNormalization(Context context, Map map, Map map1, Map map2, Map map3)
    {
        String s;
        boolean flag;
label0:
        {
            if(whitespace != null || ccase != null)
            {
                Iterator iterator = context.e.getAttributes().iterator();
                do
                {
                    if(!iterator.hasNext())
                        break;
                    Attribute attribute = (Attribute)iterator.next();
                    if(attributeNameMatch(attribute, context))
                    {
                        if(whitespace != null && !map1.containsKey(attribute))
                            map1.put(attribute, whitespace);
                        if(ccase != null && !map2.containsKey(attribute))
                            map2.put(attribute, ccase);
                    }
                } while(true);
            }
            s = name_local + ":" + name_uri;
            if(ddefault == null || map.containsKey(s) || map3.containsKey(s))
                return;
            flag = false;
            Iterator iterator1 = context.e.getAttributes().iterator();
            Attribute attribute1;
            do
            {
                if(!iterator1.hasNext())
                    break label0;
                attribute1 = (Attribute)iterator1.next();
            } while(!attributeNameMatch(attribute1, context));
            if(Template.isGap(attribute1) && context.sg != null)
            {
                String s1 = Template.getGap(attribute1);
                if(context.sg.getOpenAttributeGaps().contains(s1))
                {
                    flag = true;
                    break label0;
                }
            }
            return;
        }
        Attribute attribute2;
        if(name_uri == null)
        {
            attribute2 = new Attribute(name_local, ddefault);
        } else
        {
            String s2 = name_prefix;
            boolean flag1 = false;
            while(!flag1)
            {
                Namespace namespace = context.e.getNamespace(s2);
                if(namespace != null && !namespace.getURI().equals(name_uri))
                    s2 = s2 + "x";
                else
                    flag1 = true;
            }
            attribute2 = new Attribute(name_local, ddefault, Namespace.getNamespace(s2, name_uri));
        }
        if(flag)
            map3.put(s, attribute2);
        else
            map.put(s, attribute2);
    }

    String name;
    String name_local;
    String name_uri;
    String name_prefix;
    Regexp regexp;
    String whitespace;
    String ccase;
    String ddefault;
    boolean qname;
    boolean qaname;
}
